﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Runtime.Serialization;


namespace Simhopp.Common
{
    public class Listener
    {
        protected TcpClient tpC;
        private Thread newThread;
        private Stream stm;
        private BinaryFormatter binaryFormatter;
        private Action<NetworkCommand> processObject;
        private int clientNo;
        public static int noOfClients = 0;

        public Listener(TcpClient tcpCln, Action<NetworkCommand> h) 
        {
            this.tpC = tcpCln;
            this.stm = tpC.GetStream();
            this.binaryFormatter = new BinaryFormatter();
            this.processObject = h;
            this.clientNo = noOfClients++;
            this.newThread = new Thread(new ThreadStart(Run));
            this.newThread.Start();
        }

        public virtual void Run()
        {
            Object obj = null;
            do
            {
                if (tpC.Connected && stm.CanRead)
                {
                    try
                    {
                        ReceiveObject(stm);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Client disconnected");
                        MyLogger.Debug("Client disconnected - " + e.Message);
                    }
                }
            } while (tpC.Connected);
        }

        public override string ToString()
        {
            return "Client: " + clientNo;
        }

        private void ReceiveObject(Stream stm)
        {
            try
            {
                var obj = binaryFormatter.Deserialize(stm);
                processObject(obj as NetworkCommand);
            }
            catch (Exception e)
            {
                MyLogger.Debug(String.Format("Error deserializing object: {0}\n{1}", e.Message, e.StackTrace));
                tpC.Close();
            }
        }

        public void SendObject(NetworkCommand o)
        {
            if (tpC.Connected && stm.CanWrite)
            {
                try
                {
                    this.binaryFormatter.Serialize(stm, o);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Client disconnected");
                    Console.WriteLine("Client disconnected - \n" + e.Message + "\n" + e.StackTrace);
                    if ((e as SerializationException) != null)
                    {
                        Console.WriteLine("Serialiseringsfel: " + (e as SerializationException).Source + "\n" + (e as SerializationException).Data);
                    }

                }
            }
        }

        public void stop()
        {
            tpC.Close();
        }
    }
}
